package com.smart.tool.retry.core;

import java.util.concurrent.TimeUnit;

import com.google.common.base.Preconditions;

/**
 * @Author gao.gwq
 * @Version WaitStrategies.java, v 0.1 2023年09月18日 11:35 gao.gwq
 * @Description: TODO
 */
public class WaitStrategies {

    /**
     * Returns a wait strategy that sleeps a fixed amount of time before retrying.
     *
     * @param sleepTime the time to sleep
     * @param timeUnit  the unit of the time to sleep
     * @return a wait strategy that sleeps a fixed amount of time
     * @throws IllegalStateException if the sleep time is &lt; 0
     */


    public static WaitStrategy routeWaitStrategy(long sleepTime,
                                                 TimeUnit timeUnit,
                                                 WaitStrategyEnum waitStrategyEnum) throws IllegalStateException {
        if(waitStrategyEnum == WaitStrategyEnum.FIXED_WAIT){
            return  new FixedWaitStrategy(timeUnit.toMillis(sleepTime));
        }
        return new BackoffWaitStrategy(timeUnit.toMillis(sleepTime));
    }

    private static final class BackoffWaitStrategy implements WaitStrategy {
        private final long sleepTime;


        public BackoffWaitStrategy(long sleepTime) {
            Preconditions.checkArgument(sleepTime >= 0L, "sleepTime must be >= 0 but is %d", sleepTime);
            this.sleepTime = sleepTime;
        }

        @Override
        public long computeSleepTime(Attempt failedAttempt,int retryTimes) {

            return sleepTime*(1<<retryTimes);
        }
    }


    private static final class FixedWaitStrategy implements WaitStrategy {
        private final long sleepTime;

        public FixedWaitStrategy(long sleepTime) {
            Preconditions.checkArgument(sleepTime >= 0L, "sleepTime must be >= 0 but is %d", sleepTime);
            this.sleepTime = sleepTime;
        }

        @Override
        public long computeSleepTime(Attempt failedAttempt,int retryTimes) {
            return sleepTime;
        }
    }
}
